/*
 * BAT2U水质检测模块
 */
#include "head\BAT2U.h"
#include "head\MCU.h"

void BAT2U_Init()
{
    /*
     * 复用p34、p35引脚
     */
    GPIO_setAsPeripheralModuleFunctionInputPin(
            BAT2U_USCI_PORT,
            BAT2U_USCI_PIN_TX + BAT2U_USCI_PIN_RX
        );

    /*
     * 配置串口
     */
    USCI_A_UART_initParam param = {0};
    param.selectClockSource = USCI_A_UART_CLOCKSOURCE_SMCLK; //选择SMCLK为时钟源
    if(MSP430_FREQUENCY == 25165824)
    {
        param.clockPrescalar = 2621;//25,165,824
        param.secondModReg = 4;
    }
    else if(MSP430_FREQUENCY == 16777216)
    {
        param.clockPrescalar = 1747;//16,777,216
        param.secondModReg = 5;
    }
//    param.clockPrescalar = 873;//8,388,608
//    param.secondModReg = 7;//
//    param.clockPrescalar = 109; //109.22666 ~= 1048676/9600
//    param.secondModReg = 2; //0.22666*8 ~= 1.81333 ~= 2
    param.firstModReg = 0; //这个是用在过采样波特率模式，公式见用户手册36.3.10.2
    param.parity = USCI_A_UART_NO_PARITY; //奇偶校验 无校验位
    param.msborLsbFirst = USCI_A_UART_LSB_FIRST; //“控制移位寄存器的方向”，及大小端。LSB属于小端，高位字节放高端
    param.numberofStopBits = USCI_A_UART_ONE_STOP_BIT; //停止位数 一个停止位
    param.uartMode = USCI_A_UART_MODE; //普通串口模式
    param.overSampling = USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION; //低采样波特率或过采样波特率选择
    if (STATUS_FAIL == USCI_A_UART_init(BAT2U_USCI_BASE, &param)){
        return;
    }

    /*
     * 使能串口
     */
    USCI_A_UART_enable(BAT2U_USCI_BASE);//UCSWRST位置1
    //Enable Receive Interrupt
    USCI_A_UART_clearInterrupt(BAT2U_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//标志位清除
    USCI_A_UART_enableInterrupt(BAT2U_USCI_BASE,USCI_A_UART_RECEIVE_INTERRUPT);//使能位置位

    BAT2U_ConfigModule();
}

void BAT2U_ConfigModule()
{
    uint8_t returnErrer;
    if(returnErrer = BAT2U_SetNTC_B(BAT2U_MODULE_INIT_NTC_B))
    {
        __no_operation();
    }

    if(returnErrer = BAT2U_SetNTCresistance(BAT2U_MODULE_INIT_NTC_RESISTANCE))
    {
        __no_operation();
    }
//    if(returnErrer = BAT2U_CalibrationBaseline())//初始化的时候进行基线校准会无法正常工作
//    {
//        __no_operation();
//    }
}

uint8_t BAT2U_SenseCommand(uint16_t *TDS, uint16_t *temperature)
{
    uint8_t Timeing = 6;
    BAT2U_ClearRxBuff();
    //发送检测指令：A0 00 00 00 00 A0
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0xA0);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0x00);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0x00);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0x00);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0x00);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0xA0);

    //等待数据返回完成
    do{
        __delay_cycles(MSP430_FREQUENCY/2);
        Timeing--;
        if(Timeing == 0)
        {
            *TDS = 0;
            *temperature = 0;
            __no_operation();
            return 5;
        }
    }
    while(BAT2U_ReceivedData[0] == 0);

    if((BAT2U_ReceivedData[0] == 0xAA) && (BAT2U_ReceivedData[6] == 0xAB))//成功获取温度与水质数据
    {
        *TDS = ((uint16_t)BAT2U_ReceivedData[1] << 8) | BAT2U_ReceivedData[2];
        *temperature = ((uint16_t)BAT2U_ReceivedData[7] << 8) | BAT2U_ReceivedData[8];
        return 0;
    }
    else//没有成功获取温度与水质数据
    {
        *TDS = 0;
        *temperature = 0;
        uint8_t i;
        for(i = 0;i < BAT2U_RX_BUFF_LEN;i++)//找到返回的异常状态头0xac的位置
        {
            if(BAT2U_ReceivedData[i] == 0xac)
            {
                return BAT2U_ReceivedData[i+1];//发送异常头的下一个字节，及异常状态 01：命令帧异常 02：忙碌中 03：校正失败 04：检测温度超出范围
            }
        }
        return 6;//接收到了数据，但既不是温度与水质的数据，也没有得到异常报错
    }
}

int8_t BAT2U_CalibrationBaseline()
{
    uint8_t Timeing = 6;
    BAT2U_ClearRxBuff();
    //基线校准：A6 00 00 00 00 A6
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0xA6);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0x00);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0x00);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0x00);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0x00);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0xA6);

    //等待数据返回完成
    do{
        __delay_cycles(MSP430_FREQUENCY/2);
        Timeing--;
        if(Timeing == 0)
        {
            __no_operation();
            return 5;
        }
    }
    while(BAT2U_ReceivedData[0] == 0);

    uint8_t i;
    for(i = 0;i < BAT2U_RX_BUFF_LEN;i++)//找到返回的状态头0xac的位置
    {
        if(BAT2U_ReceivedData[i] == 0xac)//一旦找到就返回
        {
            return BAT2U_ReceivedData[i+1];//返回异常头的下一个字节，及异常状态 01：命令帧异常 02：忙碌中 03：校正失败 04：检测温度超出范围
        }
    }
    return 6;//接收到了数据，但既不是温度与水质的数据，也没有得到异常报错
}

int8_t BAT2U_SetNTCresistance(uint32_t NTCresistance)
{
    uint8_t *p;
    uint8_t Timeing = 6;
    uint8_t cs = 0xA3;
    p = &NTCresistance;
    uint8_t i;
    for(i = 0;i < 4;i++)
    {
        cs += p[i];
    }
    BAT2U_ClearRxBuff();
    //设置 NTC 常温电阻值：A3 00 01 86 A0 CA，1-4四个字节组成一个电阻值，最后5字节是校验和
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0xA3);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,p[3]);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,p[2]);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,p[1]);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,p[0]);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,cs);

    //等待数据返回完成
    do{
        __delay_cycles(MSP430_FREQUENCY/2);
        Timeing--;
        if(Timeing == 0)
        {
            __no_operation();
            return 5;
        }
    }
    while(BAT2U_ReceivedData[0] == 0);

    for(i = 0;i < BAT2U_RX_BUFF_LEN;i++)//找到返回的状态头0xac的位置
    {
        if(BAT2U_ReceivedData[i] == 0xac)//一旦找到就返回
        {
            return BAT2U_ReceivedData[i+1];//返回异常头的下一个字节，及异常状态 01：命令帧异常 02：忙碌中 03：校正失败 04：检测温度超出范围
        }
    }
    return 6;//接收到了数据，但既不是温度与水质的数据，也没有得到异常报错
}

int8_t BAT2U_SetNTC_B(uint16_t NTC_B)
{
    uint8_t *p;
    uint8_t Timeing = 6;
    uint8_t cs = 0xA5;
    p = &NTC_B;
    uint8_t i;
    for(i = 0;i < 2;i++)
    {
        cs += p[i];
    }
    BAT2U_ClearRxBuff();
    //设置 NTC 常温电阻值：A3 00 01 86 A0 CA，1-4四个字节组成一个电阻值，最后5字节是校验和
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0xA5);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,p[1]);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,p[0]);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0x00);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,0x00);
    USCI_A_UART_transmitData(BAT2U_USCI_BASE,cs);

    //等待数据返回完成
    do{
        __delay_cycles(MSP430_FREQUENCY/2);
        Timeing--;
        if(Timeing == 0)
        {
            __no_operation();
            return 5;
        }
    }
    while(BAT2U_ReceivedData[0] == 0);

    for(i = 0;i < BAT2U_RX_BUFF_LEN;i++)//找到返回的状态头0xac的位置
    {
        if(BAT2U_ReceivedData[i] == 0xac)//一旦找到就返回
        {
            return BAT2U_ReceivedData[i+1];//返回异常头的下一个字节，及异常状态 01：命令帧异常 02：忙碌中 03：校正失败 04：检测温度超出范围
        }
    }
    return 6;//接收到了数据，但既不是温度与水质的数据，也没有得到异常报错
}

void BAT2U_ClearRxBuff()
{
    BAT2U_ReceivedDataCount = 0;
    uint8_t i;
    for(i = 0;i < BAT2U_RX_BUFF_LEN;i++)
    {
        BAT2U_ReceivedData[i] = 0;
    }
}

//******************************************************************************
//
//This is the USCI_A0 interrupt vector service routine.
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(USCI_A0_VECTOR)))
#endif
void BAT2U_USCI_A0_ISR (void)
{
    switch (__even_in_range(UCA0IV,4)){
        case 2://Vector 2 - RXIFG
        {
            BAT2U_ReceivedData[BAT2U_ReceivedDataCount++] = USCI_A_UART_receiveData(BAT2U_USCI_BASE);
            if(BAT2U_ReceivedDataCount >= BAT2U_RX_BUFF_LEN)
            {
                BAT2U_ReceivedDataCount=0;
            }
            break;
        }
        default: break;
    }
}
